/************************************************************************
* lib.c
* Copyright (C) Lisa Milne 2013 <lisa@ltmnet.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program.  If not, see <http://www.gnu.org/licenses/>
************************************************************************/

#include "dish.h"
#include "env.h"

#include <grp.h>
#include <pwd.h>
#include <ctype.h>
#include <stdarg.h>
#include <sys/stat.h>

/* basic string hash */
unsigned int hash(char* str)
{
	unsigned int hash = 5381;
	int c;
	int i;

	if (!str)
		return 0;

	for (i=0; str[i]; i++) {
		c = str[i];
		hash = ((hash << 5)+hash)+c;
	}

	return hash;
}

/* print debug message to a log file */
void debug(char* fmt, ...)
{
#ifdef CFG_DEBUG
	static char buff[1024];
	va_list ap;
	int l;
	int fd;

	va_start(ap,fmt);
	l = vsnprintf(buff,1024,fmt,ap);
	va_end(ap);
	if (l < 1)
		return;
	fd = open("dish.log",O_WRONLY | O_CREAT | O_APPEND, S_IRUSR | S_IWUSR | S_IRGRP);
	if (fd < 0)
		return;
	write(fd,buff,l);
	close(fd);
#endif
}

/* get the user id from a user name */
uid_t get_uid(char* name)
{
	struct passwd *p = getpwnam(name);
	if (!p)
		return -1;
	return p->pw_uid;
}

/* get the group id from a group name */
gid_t get_gid(char* name)
{
	struct group *g = getgrnam(name);
	if (!g)
		return -1;

	return g->gr_gid;
}

/* get the current user's name */
char* get_username()
{
	char* n = env_get("LOGNAME");
	if (n)
		return n;
	return getlogin();
}

/* remove whitespace from beginning and end of a string */
char* trim(char* str)
{
	int l;

	while (*str && isspace(*str)) {
		str++;
	}

	l = strlen(str);
	while (--l > -1 && (!str[l] || isspace(str[l]))) {
		str[l] = 0;
	}

	return str;
}

/* is it a directory? */
int is_dir(char* p)
{
	struct stat st;
	if (stat(p,&st) == 0 && (st.st_mode&S_IFDIR))
		return 1;

	return 0;
}

/* is it a file? */
int is_file(char* p)
{
	struct stat st;
	if (stat(p,&st) == 0 && (st.st_mode&S_IFREG))
		return 1;

	return 0;
}

/* is it something? (does it exist) */
int is_something(char* p)
{
	struct stat st;
	if (stat(p,&st) == 0)
		return 1;

	return 0;
}

/* is it an executable file? */
int is_exec(char* p)
{
	struct stat st;
	if (stat(p,&st) == 0 && (st.st_mode&S_IFREG)) {
		if ((st.st_mode&S_IXOTH))
			return 1;
		if (st.st_uid == getuid() && (st.st_mode&S_IXUSR))
			return 1;
		if (st.st_gid == getgid() && (st.st_mode&S_IXGRP))
			return 1;
	}

	return 0;
}

/* print usage/help info */
void usage()
{
	printf("Usage: %s [OPTION]... [FILE]...\n\n",TARGET);
	printf("  -c <COMMAND> Execute <COMMAND>\n");
	printf("  -s Read commands from standard input.\n");
	printf("  -i Use interactive mode.\n");
	printf("  -? Show this help info.\n");
	printf("\n%s version %s - Copyright (C) Lisa 'darkrose' Milne 2013\n",TARGET,VERSION);
}

/* workout what errno is up to */
int error(char* a)
{
	switch (errno) {
	case EACCES:
		fprintf(stderr,"error: Permission denied\n");
		return 0;
		break;
	case EINTR:
		fprintf(stderr,"error: '%s' is not a directory\n",a);
		return 0;
		break;
	case EISDIR:
		fprintf(stderr,"error: '%s' is a directory\n",a);
		return 0;
		break;
	case EEXIST:
		fprintf(stderr,"error: cannot create '%s': file exists\n",a);
		return 0;
		break;
	case ENOENT:
		if (a) {
			fprintf(stderr,"error: '%s' No such file or directory\n",a);
		}else{
			fprintf(stderr,"error: No such file or directory\n");
		}
		return 0;
		break;
	case ENOTDIR:
		fprintf(stderr,"error: '%s' is not a directory\n",a);
		return 0;
		break;
	case EPERM:
		fprintf(stderr,"error: %s '%s': Operation not permitted\n",TARGET,a);
		return 0;
		break;
	case EBADF:
	case EBADMSG:
	case ECONNRESET:
	case ENOTCONN:
	case ETIMEDOUT:
	case ENOBUFS:
	case EINVAL:
	case EIO:
	case ELOOP:
	case EMFILE:
	case ENAMETOOLONG:
	case ENFILE:
	case ENOSR:
	case ENXIO:
	case EOVERFLOW:
	case EROFS:
	case EAGAIN:
	case ENOMEM:
	case ETXTBSY:
	case EFAULT:
		fprintf(stderr,"error: Internal error (%d)\n",errno);
		return 0;
		break;
	default:;
	}
	return 1;
}
